package com.onstar.cn.payme.payutil.wxpay;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.onstar.cn.common.util.CommonUtil;
import com.onstar.cn.common.util.PayMeConstants;
import com.onstar.cn.payme.response.CreateOrderResponseType;
import com.tencent.mm.opensdk.constants.Build;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import java.util.LinkedList;
import java.util.List;


/**
 * 微信支付封装
 * Created by Yonglang Hong on 2016/7/27.
 */
public class WXPayUtil {

    public static final int CODE_FAIL = 0;

    public static final int CODE_ERR = 1;

    public static final int CODE_INSTALL = 2;

    public static final int CODE_SEND_PAY = 3;

    /**
     * 微信支付返回值（在WXPayEntryActivity中onResp返回，由OrderPayActivity消费）
     */
    public static int WX_RESP_CODE = -1;

    private IWXAPI wxApi;

    public WXPayUtil(Context context) {
        wxApi = WXAPIFactory.createWXAPI(context, PayMeConstants.APP_ID);
        wxApi.registerApp(PayMeConstants.APP_ID);
    }

    public void pay(final Context context, final CreateOrderResponseType orderResponseType) {
        boolean isPaySupported = wxApi.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
        if (isPaySupported) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        String url = String.format(PayMeConstants.GET_TOKEN_URL, PayMeConstants.APP_ID, orderResponseType
                                .getPaymentParameters().getWechatSecret());
                        byte[] buf = PayUtil.httpGet(url);
                        if (buf == null || buf.length == 0) {
                            sendPayFailMsg();
                        } else {
                            String content = new String(buf);
                            JSONObject json = new JSONObject(content);
                            Log.d("WXPayUtil", "access_token: " + json.getString("access_token"));
                            if (json.has("access_token")) { // success case
                                url = String.format(PayMeConstants.GET_PREPAYID_URL, json.getString("access_token"));
                                String price = orderResponseType.getPackageInfo().getActualPrice() + "";
                                if (!CommonUtil.isNull(price) && CommonUtil.isDouble(price)) {
                                    price = ((int) (Double.parseDouble(price) * 100)) + "";
                                }
                                String params = WechatUtil.genProductParams(orderResponseType.getPackageInfo()
                                                .getPackageName(), orderResponseType.getPaymentParameters().getWechatNotifyURL(),
                                        orderResponseType.getOrderId(), orderResponseType.getPaymentParameters().getWechatPartnerID(),
                                        orderResponseType.getPaymentParameters().getWechatPartnerKey(), orderResponseType
                                                .getPaymentParameters().getWechatAppKey(), price);

                                byte[] buf1 = PayUtil.httpPost(url, params);
                                if (buf1 == null || buf1.length == 0) {
                                    sendPayFailMsg();
                                } else {
                                    String prepayIdStr = new String(buf1);
                                    Log.d("WXPayUtil", "prepayId: " + prepayIdStr);
                                    JSONObject json1 = new JSONObject(prepayIdStr);
                                    String prepayId = json1.getString("prepayid");
                                    PayReq req = new PayReq();
                                    req.appId = PayMeConstants.APP_ID;
                                    req.partnerId = orderResponseType.getPaymentParameters().getWechatPartnerID();
                                    req.prepayId = prepayId;
                                    JSONObject jsonObject = new JSONObject(params);
                                    req.nonceStr = jsonObject.getString("noncestr");
                                    req.timeStamp = String.valueOf(jsonObject.getString("timestamp"));
                                    req.packageValue = "Sign=" + jsonObject.getString("package");
                                    List<NameValuePair> signParams = new LinkedList<NameValuePair>();
                                    signParams.add(new BasicNameValuePair("appid", req.appId));
                                    signParams.add(new BasicNameValuePair("appkey", orderResponseType
                                            .getPaymentParameters().getWechatAppKey()));
                                    signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
                                    signParams.add(new BasicNameValuePair("package", req.packageValue));
                                    signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
                                    signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
                                    signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
                                    req.sign = WechatUtil.genSign(signParams);
                                    sendPay(wxApi.sendReq(req));
                                }
                            } else {
                                sendPayFailMsg();
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        sendPayErrMsg(e);
                    }
                }
            }).start();
        } else {
            sendWxInstallMsg(wxApi.isWXAppInstalled());
        }
    }

    private void sendWxInstallMsg(Boolean isInstalled) {
        Message msg = handler.obtainMessage();
        msg.what = CODE_INSTALL;
        msg.obj = isInstalled;
        handler.sendMessage(msg);
    }

    private void sendPayFailMsg() {
        handler.sendEmptyMessage(CODE_FAIL);
    }

    private void sendPay(Boolean isSend) {
        Message msg = handler.obtainMessage();
        msg.what = CODE_SEND_PAY;
        msg.obj = isSend;
        handler.sendMessage(msg);
    }

    public void sendPay(final PayReq req) {
        new Thread(new Runnable() {
            @Override
            public void run() {
//                wxApi.sendReq(req);
                sendPay(wxApi.sendReq(req));
            }
        }).start();
//        Observable.just(wxApi.sendReq(req)).subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Boolean>() {
//            @Override
//            public void call(Boolean isSend) {
//                Message msg = handler.obtainMessage();
//                msg.what = CODE_SEND_PAY;
//                msg.obj = isSend;
//                handler.sendMessage(msg);
//            }
//        });
    }



    private void sendPayErrMsg(Exception ex) {
        Message msg = handler.obtainMessage();
        msg.what = CODE_ERR;
        msg.obj = ex;
        handler.sendMessage(msg);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case CODE_ERR:
                    payListener.onPayErr((Exception) msg.obj);
                    break;
                case CODE_FAIL:
                    payListener.onPayFailed();
                    break;
                case CODE_INSTALL:
                    payListener.isWXInstalled((Boolean) msg.obj);
                    break;
                case CODE_SEND_PAY:
                    payListener.sendPayReq((Boolean) msg.obj);
                    break;
            }
        }
    };

    public static void resetWXPayRespCode() {
        WX_RESP_CODE = -1;
    }

    private wxpayListener payListener;

    public void setPayListener(wxpayListener payListener) {
        this.payListener = payListener;
    }

    public interface wxpayListener {

        void isWXInstalled(boolean isInstall);

        void onPayFailed();

        void onPayErr(Exception e);

        void sendPayReq(Boolean isSend);

    }

}
